#include <stdio.h> //open_memstream
#include <curl/curl.h>  
#include <stdlib.h>
#include <string.h>
#include "cJSON.h"
#include "auth.h"


char* get_token(const char* api_key, const char* secret_key)
{


    FILE *fp;

    //以只写方式打开文件
    //fp = fopen("hello.txt", "w");
    //响应消息的地址
    char *response = NULL;
    //响应消息的长度
    size_t resplen = 0;
    //创建内存文件，当通过文件句柄写入数据时，会自动分配内存
    fp = open_memstream(&response, &resplen);
    if (fp == NULL) //打开文件失败，打印错误信息并退出
    {
        perror("open_memstream() failed");
        return NULL;
    }


    //初始化HTTP客户端
    CURL *curl = curl_easy_init();

    if (curl == NULL)
    {
        perror("curl_easy_init() failed");
        return NULL;
    }

    char *uri = NULL;

    //生成拼接uri,asprintf会自动分配内存
    asprintf(&uri, 
            "https://openapi.baidu.com/oauth/2.0/token?grant_type=client_credentials&client_id=%s&client_secret=%s", 
            api_key,
            secret_key);

    //准备HTTP请求消息，设置API地址（URI）
    curl_easy_setopt(curl, CURLOPT_URL, uri);
    
    //如果不指定写入的文件，libcurl会把服务器响应消息中的内容打印到屏幕上
    //如果指定了文件句柄，libcurl会把服务器响应消息中的内容写入文件
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);

    //发送HTTP请求消息，等待服务器的响应消息
    CURLcode error = curl_easy_perform(curl);
    if (error != CURLE_OK)
    {
        fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(error));
        curl_easy_cleanup(curl);
        free(uri);
        fclose(fp);
        free(response);
        return NULL;
    }

    //释放HTTP客户端申请的资源
    curl_easy_cleanup(curl);

    //释放读取网址分配asprintf的内存
    free(uri);

    //关闭内存文件
    fclose(fp);

    //打印返回
    //puts(response);

    cJSON* json = cJSON_Parse(response);
    if (json == NULL)
    {
        const char *error_pos = cJSON_GetErrorPtr();
        if (error_pos != NULL)
        {
            fprintf(stderr, "Error before: %s\n", error_pos);
        }
        return NULL;
    }

    //获取JSON报文中的acess_token字段
    cJSON *access_token = cJSON_GetObjectItemCaseSensitive(json, "access_token");

    if (!cJSON_IsString(access_token))
    {
        cJSON *error_description = cJSON_GetObjectItemCaseSensitive(json, "error_description");
        fprintf(stderr, "%s \n", error_description->valuestring);
        return NULL;
    }


    //使用完之后，需要使用free释放token
    char* token = strdup(access_token->valuestring);

    //free(response);
    cJSON_Delete(json);

    return token;
}